home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / PlainText / PlainText.c < prev    next >
Text File  |  1994-02-03  |  61KB  |  2,530 lines

  1. /*-----------------------------------------------------------------------
  2.  
  3.     Wednesday, January 26, 1994 11:53:04 PM
  4.  
  5.     Plain Text
  6.     by Mel Park
  7.     mpark@utmem1.utmem.edu
  8.     
  9.     This code is in the Public Domain and is freely distributable
  10.     
  11.     The style of coding in which Plain Text is written is a bit unusual. 
  12.     It is a pure C implimentation of ideas contained in the object class 
  13.     library published in "Elements of C++ Macintosh Programming" by Dan 
  14.     Weston. Objects are implemented as structures and member functions 
  15.     are implemented as pointers to subroutines contained within the object 
  16.     structure. Consider it assembly-language C++.
  17.     
  18.     The text engine is from TE32K, by Roy Wood. I have extensively 
  19.     modified it for the family of applications related to PlainText.
  20.     
  21.     That family is a number of tools for mapping for which a worksheet-
  22.     based front end was desirable.
  23.  
  24. ------------------------------------------------------------------------*/
  25.  
  26. #include "PlainText.h"
  27. #include "PTGlobs.h"
  28.  
  29. /*---------------------------- Declarartions ----------------------------*/
  30.  
  31. extern void _DataInit();            /* this is the C initialization code */
  32. extern void nullWindowMethod(WindowPtr);
  33. extern void nullEventMethod(WindowPtr,EventRecord *);
  34. extern int nullIntMethod(WindowPtr);
  35. extern void DoPageScroll(ControlHandle,short);
  36. extern void Scroll(ControlHandle,short);
  37. extern void ScrollClick(WindowPtr,EventRecord *);
  38. extern void textDestructor(WindowPtr wind);
  39.  
  40. void FatalError(void);
  41.  
  42. int SetUpWorld(void);
  43. void QuitTime(void);
  44. void ActivateEvt(EventRecord *);   
  45. void OSEvent(EventRecord *);
  46. void CheckForDASwitch(WindowPtr);
  47. void DoSuspend(EventRecord *,Boolean);
  48. void DoResume(EventRecord *,Boolean);
  49. void UpdateEvt(EventRecord *);
  50. static void DoKey(EventRecord *);
  51. static void DoMouse(EventRecord *);
  52. int CloseADoc(WindowPtr);
  53. WindowPtr FindDoc(WindowPtr);
  54. void AdjustMenus(WindowPtr wind);
  55.  
  56. static DocumentPeek OpenClipboardWindow(void);
  57. static void setUseWorksheet(void);
  58.  
  59. static void DoAboutDialog(void);
  60.  
  61. void OpenOldDoc(int);
  62. WindowPtr InitOldDoc(OSType, FSSpecPtr);
  63. Boolean OpenDocFromFinder(void);
  64. Boolean AcceptableFileType(OSType);
  65. void OpenNewDoc(void);
  66. void GiveClipToSystem(void);
  67. void GetClipFromSystem(void);
  68.  
  69. void WindowMenuSelect(short);
  70.  
  71. void MakeWorksheetDoc(FSSpecPtr);
  72. void sortMarks(DocumentPeek, Boolean);
  73. void FillMarkMenu(DocumentPeek);
  74. void InitAEStuff(void);
  75. void DoHighLevel(EventRecord *);
  76.  
  77. pascal Boolean listFilter(DialogPtr,EventRecord *,short *);
  78. void UpdateList (ListHandle);
  79.  
  80. pascal OSErr AEOpenHandler(AppleEvent *, AppleEvent *, long);
  81. pascal OSErr AEOpenDocHandler(AppleEvent *, AppleEvent *, long);
  82. pascal OSErr AEPrintHandler(AppleEvent *, AppleEvent *, long);
  83. pascal OSErr AEQuitHandler(AppleEvent *, AppleEvent *, long);
  84. OSErr processOpenPrint(AppleEvent *, Boolean);
  85.  
  86. void SizeDocWindow(WindowPtr, Rect *,Boolean);
  87. void TileWindows(void);
  88. void StackWindows(void);
  89.  
  90. MarkRecPtr GetIndMark(Ptr, short);
  91.  
  92.  
  93. /*----------------------------- RestartProc -----------------------------*/
  94.  
  95. restartProc()
  96. {
  97.     QuitTime();
  98. }
  99.  
  100. /*----------------------------- doMessage --------------------------------*/
  101.  
  102. pascal Boolean SimpleDialogFilter(DialogPtr dialog, EventRecord *theEvent, short *itemHit)
  103. {
  104. #pragma unused(dialog)
  105.     char key;
  106.     
  107.     if(theEvent->what==keyDown) {
  108.         key=theEvent->message&charCodeMask;
  109.         switch(key) {
  110.             case 3: case 13:        /* Enter or CR */
  111.                 *itemHit=1;
  112.                 return true;
  113.             case 46:                /* Period */
  114.                 if(theEvent->modifiers&0x100) {
  115.             case 27:                /* Escape */
  116.                     *itemHit=2;
  117.                     return true;
  118.                 }
  119.             default:
  120.                 return false;
  121.         }
  122.     }
  123.     return false;
  124. }
  125.  
  126. pascal void doMessage(short message)    /* Uses Str resource 130 */ 
  127. {
  128.     DialogPtr dialogP;
  129.     short itemType;
  130.     Rect box;
  131.     Handle itemHand;
  132.     Str255 buf;
  133.     
  134.     GetIndString(buf,130,message);
  135.     ParamText(buf,(StringPtr)"",(StringPtr)"",(StringPtr)"");
  136.     dialogP=GetNewDialog(MessageDialog,(Ptr)NIL,(WindowPtr)-1);
  137.     if (dialogP==NIL)
  138.         FatalError();
  139.     else {
  140.         GetDItem(dialogP,4,&itemType,&itemHand,&box);
  141.         SetDItem(dialogP,4,itemType,(Handle)doButton,&box);
  142.         InitCursor();
  143.         ModalDialog(SimpleDialogFilter,&itemType);
  144.         DisposDialog(dialogP);
  145.     }
  146. }
  147.  
  148. void doDiagnosticMessage(short message, short errNum)
  149. {
  150.     DialogPtr dialogP;
  151.     short item;
  152.     Str255 buf,num;
  153.     
  154.     GetIndString(buf,130,message);
  155.     NumToString(errNum,num);
  156.     ParamText(buf,num,(StringPtr)"",(StringPtr)"");
  157.     dialogP=GetNewDialog(MessageDialog,(Ptr)NIL,(WindowPtr)-1);
  158.     if (dialogP==NIL)
  159.         FatalError();
  160.     else {
  161.         InitCursor();
  162.         ModalDialog(SimpleDialogFilter,&item);
  163.         DisposDialog(dialogP);
  164.     }
  165. }
  166.  
  167. /*------------------------------- SetUpWorld -----------------------------*/
  168.  
  169. #pragma segment setup
  170.  
  171. int SetUpWorld(void)
  172. {
  173.     OSErr err;
  174.     short MBarHeight;
  175.     int i,response=0;
  176.     GDHandle maingd;
  177.     
  178.     err=Gestalt(gestaltSystemVersion,&response);
  179.     response&=0xFFFF;
  180.     if(err!=noErr || response<0x604) {
  181.         SysBeep(7);
  182.         doMessage(15);
  183.         return false;
  184.     }
  185.     InitGraf(&qd.thePort);
  186.     InitFonts();
  187.     FlushEvents(everyEvent,nullStopMask);
  188.     InitWindows();
  189.     InitMenus();
  190.     TE32KInit();
  191.     InitDialogs((ResumeProcPtr)restartProc);
  192.  
  193.     InitACurs(160);            /* Init the beachball cursor */
  194.     InitCursor();
  195.     MaxApplZone();
  196.     
  197.     MoreMasters();            /* Make sure all the master   */
  198.  
  199.     /* check if WNE is implemented, according to Technical Node #158 */
  200.     
  201.     response=0;
  202.     err=Gestalt(gestaltKeyboardType,&response);
  203.     gMacPlusKBD=(err==noErr && response<=3);
  204.     
  205.     response=0;
  206.     err=Gestalt(gestaltQuickdrawVersion,&response);
  207.     gHasColorQD=(err==noErr && (response&0xFF00));
  208.     
  209.     for (i=0;i<MAXWINDS;i++) {
  210.         Documents[i].fDocWindow=NULL;
  211.     }
  212.     
  213.     MBarHeight=GetMBarHeight();
  214.     SetRect(&DragBoundsRect,0,0,512,342);
  215.     if(gHasColorQD) {
  216.         maingd=GetMainDevice();
  217.         DragBoundsRect=(**maingd).gdRect;
  218.     }
  219.     InsetRect(&DragBoundsRect,4,4);
  220.     DragBoundsRect.top+=(MBarHeight-4);
  221.     
  222.     gInBackground = false;
  223.     gDAonTop = false;
  224.     gLastScrapCount = 0;
  225.     
  226.     GetClipFromSystem();
  227.     
  228.     if(gHasColorQD) {
  229.         if(!(DefaultPalette=GetNewPalette(130))) {
  230.             return 0;
  231.         }
  232.         if(!(MyCMHandle=(CTabHandle)NewHandle(sizeof(ColorTable)))) {
  233.             doMessage(14);
  234.             return 0;
  235.         }
  236.         Palette2CTab(DefaultPalette,MyCMHandle);  
  237.     }
  238.     
  239.     PTScratch = NewHandle(1024);
  240.     if(!PTScratch)
  241.         return 0;
  242.         
  243.     gPlainTextRefNum = CurResFile();
  244.  
  245.     PenNormal();
  246.     return true;
  247. }
  248.     
  249. /*----------------------------- setUpMenus ------------------------------*/
  250.  
  251. setUpMenus()
  252. {    
  253.     DeskMenu=GetMenu(DESK_ID);
  254.     AddResMenu(DeskMenu,'DRVR');
  255.     InsertMenu(DeskMenu,0);
  256.     FileMenu=GetMenu(FILE_ID);
  257.     InsertMenu(FileMenu,0);
  258.     EditMenu=GetMenu(EDIT_ID);
  259.     InsertMenu(EditMenu,0);
  260.     FindMenu=GetMenu(FIND_ID);
  261.     InsertMenu(FindMenu,0);
  262.     MarkMenu=GetMenu(MARK_ID);
  263.     InsertMenu(MarkMenu,0);
  264.     WindowMenu=GetMenu(WINDOW_ID);
  265.     InsertMenu(WindowMenu,0);
  266.     ConvertMenu=GetMenu(CONVERT_ID);
  267.     InsertMenu(ConvertMenu,0);
  268.  
  269.     AdjustMenus((WindowPtr)nil);
  270.     DrawMenuBar();
  271.     return;
  272. }
  273.  
  274. #pragma segment Main
  275.  
  276. void FatalError(void)
  277. {
  278.     SysBeep(5);
  279.     ExitToShell();
  280. }
  281.  
  282. void ActivateEvt(EventRecord *EvtPtr)           
  283. {
  284.     WindowPtr targetWindow;
  285.     
  286.     targetWindow=(WindowPtr)EvtPtr->message;         /* What window is it in?  */
  287.     
  288.     if(FindDoc(targetWindow))             /* Is it a Documents window? */
  289.         DoActivate(targetWindow,EvtPtr);
  290. }
  291.  
  292. /*    FrontLayer() substitutes for FrontWindow(). It never returns a pane
  293.     but rather its parent window. */
  294.     
  295. WindowPtr FrontLayer(void)
  296. {
  297.     WindowPtr wind;
  298.     
  299.     if(wind = FrontWindow()) {
  300.         if(((DocumentPeek)wind)->homeWindow)
  301.             return ((DocumentPeek)wind)->homeWindow;
  302.     }
  303.     return wind;
  304. }
  305.  
  306. static void DoAboutDialog(void)
  307. {
  308.     short itemHit,dWidth;
  309.     DialogPtr abtDlg;
  310.     DialogTHndl dT;
  311.     Handle version;
  312.     GrafPtr oldPort;
  313.  
  314.     dT = (DialogTHndl)GetResource('DLOG',1001);
  315.     LoadResource((Handle)dT);
  316.     
  317.     dWidth=(**dT).boundsRect.right-(**dT).boundsRect.left;
  318.     (**dT).boundsRect.left=(DragBoundsRect.right+DragBoundsRect.left-dWidth)/2;
  319.     (**dT).boundsRect.right=(**dT).boundsRect.left + dWidth;
  320.     
  321. #if 0
  322.     abtDlg=GetNewDialog(1001,NULL,(WindowPtr)(-1));
  323.         
  324.     itemHit=30;    /* just any big number */
  325.     while (itemHit>10) ModalDialog(SimpleDialogFilter,&itemHit);
  326.     DisposDialog(abtDlg);
  327. #endif
  328.  
  329.     dT = (DialogTHndl)GetResource('DLOG',1002);
  330.     LoadResource((Handle)dT);
  331.     
  332.     dWidth=(**dT).boundsRect.right-(**dT).boundsRect.left;
  333.     (**dT).boundsRect.left=(DragBoundsRect.right+DragBoundsRect.left-dWidth)/2;
  334.     (**dT).boundsRect.right=(**dT).boundsRect.left + dWidth;
  335.  
  336.     abtDlg=GetNewDialog(1002,NULL,(WindowPtr)(-1));
  337.     version = GetResource('vers',2);
  338.     
  339.     GetPort(&oldPort);
  340.     SetPort(abtDlg);
  341.     TextFont(4);
  342.     TextSize(9);
  343.     HLock(version);
  344.     
  345.     itemHit=30;    /* just any big number */
  346.     while (itemHit>10) {
  347.         MoveTo(280,240);
  348.         DrawString((StringPtr) *version + *(*version+6) + 7);
  349.         ModalDialog(SimpleDialogFilter,&itemHit);
  350.     }
  351.     HUnlock(version);
  352.     DisposDialog(abtDlg);
  353.     SetPort(oldPort);
  354. }
  355.  
  356. /*------------------------------- doMenu ---------------------------------*/
  357.  
  358. DoMenu(long menuResult,WindowPtr wind,short modifiers)
  359. {
  360.     int menuID,itemNumber;
  361.     short itemMark;
  362.     Str255 daName;
  363.     GrafPtr theCurrentPort;
  364.     
  365.     menuID=HiWord(menuResult);
  366.     itemNumber=LoWord(menuResult);
  367.     InitCursor();
  368.     
  369.     /* Give current doc a chance to handle the item. */
  370.     if(wind && (*((DocumentPeek)wind)->doDocMenuCommand)(wind,menuID,itemNumber,modifiers)) {
  371.         HiliteMenu(0);
  372.         return;
  373.     }
  374.     
  375.     switch(menuID) {
  376.         case DESK_ID:
  377.             if (itemNumber==1) 
  378.                 DoAboutDialog();
  379.             else if (itemNumber==0)     /* nested menus */
  380.                 ;
  381.             else {                        /* a desk accessory */
  382.                 GetItem(DeskMenu,itemNumber,&daName);
  383.                 GetPort(&theCurrentPort);
  384.                 OpenDeskAcc(&daName);
  385.                 SetPort(theCurrentPort);
  386.             }
  387.             break;
  388.         case FILE_ID:    /* the file menu */
  389.             switch(itemNumber) {
  390.                 case iNew:
  391.                     OpenNewDoc();
  392.                     break;
  393.                 case iOpen:
  394.                     OpenOldDoc(modifiers&optionKey);
  395.                     break;
  396.                 case iClose:
  397.                     if (wind) 
  398.                         CloseADoc(wind);
  399.                     break;
  400.                 case iSave:
  401.                     if(wind)
  402.                         DoSave(wind);
  403.                     break;
  404.                 case iSaveAs:
  405.                     if(wind)
  406.                         DoSaveAs(wind);
  407.                     break;
  408.                 case iSaveACopy:
  409.                     if(wind)
  410.                         DoSaveACopy(wind);
  411.                     break;
  412.                 case iRevert:
  413.                     if(wind)
  414.                         DoRevert(wind);
  415.                     break;
  416.                 case iPageSetup:
  417.                     if(wind)
  418.                         (*((DocumentPeek)wind)->doPageSetup)(wind);
  419.                     break;
  420.                 case iPrint:
  421.                     if(wind)
  422.                         (*((DocumentPeek)wind)->doPrint)(wind);
  423.                     break;
  424.                 case iQuit:
  425.                     QuitTime();
  426.                     break;
  427.                 default:
  428.                     break;
  429.             }
  430.             break;
  431.         case EDIT_ID:    /* the edit menu */
  432.             switch(itemNumber) {
  433.                 case iUndo:
  434.                     (*((DocumentPeek)wind)->doUndo)(wind);
  435.                     break;
  436.                 case iCut:
  437.                     (*((DocumentPeek)wind)->doCut)(wind);
  438.                     break;
  439.                 case iCopy:
  440.                     (*((DocumentPeek)wind)->doCopy)(wind);
  441.                     break;
  442.                 case iPaste:
  443.                     (*((DocumentPeek)wind)->doPaste)(wind);
  444.                     break;
  445.                 case iClear:
  446.                     (*((DocumentPeek)wind)->doClear)(wind);
  447.                     break;
  448.                 case iSelectAll:
  449.                     (*((DocumentPeek)wind)->doSelectAll)(wind);
  450.                     break;
  451.                 case iShowClipboard:
  452.                     if(gClipboardDoc) 
  453.                         CloseADoc((WindowPtr)gClipboardDoc);
  454.                     else 
  455.                         gClipboardDoc=OpenClipboardWindow();
  456.                     break;
  457.                 case iWorksheet:
  458.                     setUseWorksheet();
  459.                     break;
  460.                 default:
  461.                     break;
  462.             }
  463.             break;
  464.         case FIND_ID:        /* the Find menu */
  465.             switch(itemNumber) {
  466.                 case iDisplaySelection:
  467.                     DisplaySelection(FrontLayer());
  468.                     break;
  469.                 case iReplace:
  470.                     break;
  471.                 case iReplaceSame:
  472.                     break;
  473.                 default:
  474.                     break;
  475.             }
  476.             break;
  477.         case MARK_ID:
  478.             if(itemNumber==iAlphabetical) {    
  479.                 GetItemMark(MarkMenu,iAlphabetical,&itemMark);
  480.                 sortMarks((DocumentPeek)wind,(Boolean)itemMark);
  481.             } 
  482.             break;
  483.         case WINDOW_ID:
  484.             if(itemNumber==iTileWindows) {
  485.                 TileWindows();
  486.             } else if(itemNumber==iStackWindows) {
  487.                 StackWindows();
  488.             } else {
  489.                 WindowMenuSelect(itemNumber-3);
  490.             }
  491.             break;
  492.         default:
  493.             break;
  494.     }    
  495.     return;
  496. }
  497.  
  498. void QuitTime(void)
  499. {
  500.     int i;
  501.     
  502.     for(i=MAXWINDS-1;i>=0;i--) {
  503.         if (Documents[i].docData) {
  504.             if(!CloseADoc((WindowPtr)&Documents[i]))
  505.                 return;        /* Couldn't close a doc. Abort Quit. */
  506.         }
  507.     }
  508.     GiveClipToSystem();
  509.     gPlainTextIsRunning=false;
  510. }
  511.  
  512. WindowPtr FindDoc(WindowPtr wind)
  513. {
  514.     int i;
  515.     
  516.     for(i=0;i<MAXWINDS;i++) {
  517.         if(wind == &Documents[i])
  518.             return wind;
  519.     }
  520.     return 0;
  521. }
  522.  
  523. void AppIdle(WindowPtr curDoc)
  524. {
  525.     if(curDoc)
  526.         (*((DocumentPeek)curDoc)->doIdle)(curDoc);
  527. }
  528.     
  529. /*------------------------------- EventLoop -----------------------------*/
  530.  
  531. static void eventLoop(void)
  532. {
  533.     EventRecord theEvent;
  534.     int gotEvent;
  535.     WindowPtr theFrontWindow;
  536.     
  537.     while(gPlainTextIsRunning) {
  538.         theFrontWindow = FrontWindow();
  539.         CheckForDASwitch(theFrontWindow);
  540.         
  541.         gotEvent=WaitNextEvent(everyEvent,&theEvent,(long)NIL,(RgnHandle)NIL);
  542.         
  543.         if(gotEvent) {
  544.             switch(theEvent.what) {
  545.                 case osEvt:
  546.                     OSEvent(&theEvent);
  547.                     break;
  548.                 case mouseDown:
  549.                     DoMouse(&theEvent);
  550.                     break;
  551.                 case keyDown:
  552.                 case autoKey:
  553.                     DoKey(&theEvent);
  554.                     break;
  555.                 case activateEvt:
  556.                     ActivateEvt(&theEvent);
  557.                     break;
  558.                 case updateEvt:
  559.                     UpdateEvt(&theEvent);
  560.                     break;
  561.                 case nullEvent:
  562.                     AppIdle(FindDoc(FrontLayer()));
  563.                     break;
  564.                 case kHighLevelEvent:
  565.                     DoHighLevel(&theEvent);
  566.                 default:
  567.                     break;
  568.             }
  569.         } else 
  570.             AppIdle(FindDoc(FrontLayer()));
  571.     }
  572. }
  573.  
  574. void DoHighLevel(EventRecord *AERecord)
  575. {
  576.     OSErr myErr;
  577.     myErr=AEProcessAppleEvent(AERecord);
  578. }
  579.  
  580. void UpdateEvt(EventRecord *event)
  581. {
  582.     WindowPtr wind;
  583.     
  584.     wind = (WindowPtr) event->message;
  585.     if(FindDoc(wind))
  586.         DoTheUpdate(wind,event);
  587. }
  588.  
  589. Boolean isEditKey(EventRecord *theEvent)
  590. {
  591.     int keyCode,ch;
  592.     
  593. /*    This routine returns true if the key is an arrow key. */
  594.  
  595.     if(gMacPlusKBD) {
  596.         switch(keyCode = (int)(theEvent->message&keyCodeMask)>>8) {
  597.             case 0x42:
  598.                 theEvent->message=(theEvent->message&~charCodeMask)|RIGHTARROW;
  599.                 break;
  600.             case 0x46:
  601.                 theEvent->message=(theEvent->message&~charCodeMask)|LEFTARROW;
  602.                 break;
  603.             case 0x48:
  604.                 theEvent->message=(theEvent->message&~charCodeMask)|DOWNARROW;
  605.                 break;
  606.             case 0x4D:
  607.                 theEvent->message=(theEvent->message&~charCodeMask)|UPARROW;
  608.                 break;
  609.             default:
  610.                 break;
  611.         }
  612.     }
  613.     ch=theEvent->message&charCodeMask;
  614.     return ch==LEFTARROW || ch==RIGHTARROW || ch==DOWNARROW || ch==UPARROW;
  615. }
  616.  
  617. static void DoKey(EventRecord *theEvent)
  618. {
  619.     long ch;
  620.     WindowPtr wind;
  621.     
  622. /*
  623.     TE32K recognizes these char codes (decimal):
  624.         LeftArrow     28 
  625.         RightArrow     29
  626.         UpArrow     30
  627.         DownArrow     31
  628.     MacPlus Keyboard virtual codes are (hex):
  629.         LeftArrow     46
  630.         RightArrow     42
  631.         UpArrow     4D
  632.         DownArrow     48
  633.     MacII codes are:
  634.         LeftArrow     7B
  635.         RightArrow     7C
  636.         UpArrow     7E
  637.         DownArrow     7D
  638.     Extended codes are:
  639.         63    copy            10 (DLE)
  640.         72    help/insert        05 (ENQ)
  641.         73    home            01 (SOH)
  642.         74    pg up            0B (VT)
  643.         75    del fwrd        7F (DEL)
  644.         76    paste            10
  645.         77    end                04 (EOT)
  646.         78    cut                10
  647.         79    pg down            0C (FF)
  648.         7A    undo            10
  649. */
  650.     
  651.     wind=FrontLayer();    
  652.     if (theEvent->modifiers&cmdKey) {
  653.         AdjustMenus(wind);    /* Have to adjust before calling MenuKey */
  654.         ch=MenuKey((short)theEvent->message&charCodeMask);
  655.         if(ch&0xFFFF0000) {    /* There is an enabled menu item for this command-key equivalent. */
  656.             DoMenu(ch,wind,theEvent->modifiers);
  657.             while(TickCount() < theEvent->when+6) ;
  658.             HiliteMenu(0);
  659.             return;
  660.         } else if(!isEditKey(theEvent))    /* only cmd-arrow keys get further processing */
  661.             return;
  662.     }
  663.     /* The cut, copy, paste, and undo keys are processed here. */
  664.     
  665.     if((ch=theEvent->message&charCodeMask) == 0x10) {
  666.         switch (theEvent->message&keyCodeMask) {
  667.             case 0x6300:
  668.                 if(((DocumentPeek)wind)->fHaveSelection) {
  669.                     FlashMenuBar(EDIT_ID);
  670.                     (*((DocumentPeek)wind)->doCopy)(wind);
  671.                     while(TickCount() < theEvent->when+6) ;
  672.                     FlashMenuBar(EDIT_ID);
  673.                 }
  674.                 return;
  675.             case 0x7600:
  676.                 FlashMenuBar(EDIT_ID);
  677.                 (*((DocumentPeek)wind)->doPaste)(wind);
  678.                 while(TickCount() < theEvent->when+6) ;
  679.                 FlashMenuBar(EDIT_ID);
  680.                 return;
  681.             case 0x7800:
  682.                 if(((DocumentPeek)wind)->fHaveSelection) {
  683.                     FlashMenuBar(EDIT_ID);
  684.                     (*((DocumentPeek)wind)->doCut)(wind);
  685.                     while(TickCount() < theEvent->when+6) ;
  686.                     FlashMenuBar(EDIT_ID);
  687.                 }
  688.                 return;
  689.             case 0x7A00:
  690.                 if(((DocumentPeek)wind)->fNeedtoSave) {
  691.                     FlashMenuBar(EDIT_ID);
  692.                     (*((DocumentPeek)wind)->doUndo)(wind);
  693.                     while(TickCount() < theEvent->when+6) ;
  694.                     FlashMenuBar(EDIT_ID);
  695.                 }
  696.                 return;
  697.             default:
  698.                 break;
  699.         }
  700.     }
  701.     if(ch==0x0B)         /* Page up */
  702.         DoPageScroll(((DocumentPeek)wind)->vScroll,-inPageUp);
  703.     else if(ch==0x0C)    /* Page down */
  704.         DoPageScroll(((DocumentPeek)wind)->vScroll,-inPageDown);
  705.     else if(ch==0x01)    /* home */
  706.         Scroll(((DocumentPeek)wind)->vScroll,-32768);
  707.     else if(ch==0x04)    /* end */
  708.         Scroll(((DocumentPeek)wind)->vScroll,32767);
  709.     else {
  710.         if (gMacPlusKBD && theEvent->modifiers&shiftKey) 
  711.             isEditKey(theEvent);
  712.         (*((DocumentPeek)wind)->doKeyDown)(wind,theEvent);
  713.     }
  714. }
  715.  
  716. void ClearVariableMenu(MenuHandle menuH, int topItem)
  717. {
  718.     int i;
  719.     
  720.     for(i=CountMItems(menuH);i>topItem;i--)
  721.         DelMenuItem(menuH,i);
  722. }
  723.  
  724. WindowPtr TargetWindow(void)
  725. {
  726.     WindowPeek wind;
  727.     
  728.     if(wind = (WindowPeek)FrontLayer()) {
  729.         for(wind=wind->nextWindow;wind;wind=wind->nextWindow) {
  730.             if(wind->windowKind==9 || wind->windowKind==13)
  731.                 return (WindowPtr)wind;
  732.         }
  733.     }
  734.     return 0;
  735. }
  736.  
  737. void AdjustMenus(WindowPtr wind)
  738. {
  739.     int i,cnt,k;
  740.     DocumentPeek target;
  741.     Str255 itemText;
  742.     
  743.     ClearVariableMenu(WindowMenu,3);
  744.     
  745.     target = (DocumentPeek)TargetWindow();
  746.     for(i=cnt=0;i<MAXWINDS && cnt<NumWindows;i++) {
  747.         if(Documents[i].fDocWindow) {
  748.             cnt++;
  749.             if(((WindowPeek)(Documents+i))->windowKind!=10) {    /* Don't bother with panes */
  750.                 k=1;
  751.                 if(wind == (Documents+i)) {
  752.                     *(itemText+k++)='!';
  753.                     *(itemText+k++)=checkMark;
  754.                 }
  755.                 if((Documents+i) == target) {
  756.                     *(itemText+k++)='!';
  757.                     *(itemText+k++)=0xA5;
  758.                 }
  759.                 if(Documents[i].fNeedtoSave) {
  760.                     *(itemText+k++)='<';
  761.                     *(itemText+k++)='U';
  762.                 }
  763.                 GetWTitle((WindowPtr)(Documents+i),itemText+k);
  764.                 p2cstr(itemText+k);
  765.                 *itemText=strlen(itemText+1);
  766.                 AppendMenu(WindowMenu,itemText);
  767.             }
  768.         }
  769.     }
  770.     CalcMenuSize(WindowMenu);
  771.     
  772.     if(wind) {
  773.         if(((DocumentPeek)wind)->marks) {
  774.             EnableItem(MarkMenu,iMark);
  775.             EnableItem(MarkMenu,iUnmark);
  776.             EnableItem(MarkMenu,iAlphabetical);
  777.         } else {
  778.             EnableItem(MarkMenu,iMark);
  779.             DisableItem(MarkMenu,iUnmark);
  780.             DisableItem(MarkMenu,iAlphabetical);
  781.         }
  782.         EnableItem(MarkMenu,0);
  783.         (*((DocumentPeek)wind)->adjustDocMenus)(wind);
  784.     } else {
  785.         DisableItem(FileMenu,iClose);
  786.         DisableItem(FileMenu,iSave);
  787.         DisableItem(FileMenu,iSaveAs);
  788.         DisableItem(FileMenu,iRevert);
  789.         DisableItem(FileMenu,iPageSetup);
  790.         DisableItem(FileMenu,iPrint);
  791.         DisableItem(EditMenu,iUndo);
  792.         DisableItem(EditMenu,iCut);
  793.         DisableItem(EditMenu,iCopy);
  794.         DisableItem(EditMenu,iPaste);
  795.         DisableItem(EditMenu,iClear);
  796.         DisableItem(EditMenu,iSelectAll);
  797.         DisableItem(EditMenu,iFormat);
  798.         DisableItem(EditMenu,iAlign);
  799.         DisableItem(EditMenu,iShiftRight);
  800.         DisableItem(EditMenu,iShiftLeft);
  801.         EnableItem(EditMenu,iWorksheet);
  802.         EnableItem(FileMenu,0);
  803.         EnableItem(EditMenu,0);
  804.         DisableItem(FindMenu,0);
  805.         DisableItem(MarkMenu,0);
  806.         DisableItem(WindowMenu,0);
  807.         DisableItem(ConvertMenu,0);
  808.  
  809.     }
  810.     SetMenuAbility(EditMenu,iShowClipboard,TE32KScrpHandle && TE32KScrpLength > 0);
  811.  
  812. }
  813.  
  814. static void DoMouse(EventRecord *theEvent)
  815. {
  816.     Point eventPt;
  817.     short windowCode;
  818.     WindowPtr wind;
  819.     
  820.     eventPt=theEvent->where;
  821.     
  822.     windowCode=FindWindow(eventPt,&wind);
  823.     
  824.     switch(windowCode) {
  825.         case inSysWindow:
  826.             SystemClick(theEvent,wind);
  827.             break;
  828.         case inMenuBar:
  829.             wind=FrontLayer();
  830.             AdjustMenus(wind);
  831.             DoMenu(MenuSelect(theEvent->where),wind,theEvent->modifiers);
  832.             HiliteMenu(0);
  833.             break;
  834.         case inGoAway:
  835.             if (TrackGoAway(wind,theEvent->where)) 
  836.                 CloseADoc(wind);
  837.             break;
  838.         case inDrag:
  839.             DragWindow(wind,eventPt,&DragBoundsRect);
  840.             break;
  841.         case inGrow:
  842.             (*((DocumentPeek)wind)->doGrow)(wind,theEvent);
  843.             break;
  844.         case inZoomIn:
  845.         case inZoomOut:
  846.             if (TrackBox(wind,theEvent->where,windowCode))    /* point passed by value */
  847.                 (*((DocumentPeek)wind)->doZoom)(wind,windowCode);
  848.             break;
  849.         case inContent:
  850.             if(wind!=FrontLayer()) {
  851.                 SelectWindow(wind);
  852.                 break;
  853.             } else 
  854.                 DoContent(wind,theEvent);
  855.             break;
  856.         case inDesk:
  857.             break;
  858.         default:
  859.             break;
  860.     }
  861.     return;
  862. }
  863.  
  864. void clipboardDestructor(WindowPtr wind)
  865. {
  866.     Str255 clipName;
  867.     
  868.     textDestructor(wind);
  869.     gClipboardDoc = 0;
  870.     GetIndString(clipName,129,3);
  871.     SetItem(EditMenu,iShowClipboard,clipName);
  872. }
  873.  
  874. void clipboardAdjustDocMenus(WindowPtr)
  875. {
  876.     
  877.     /* File Menu */
  878.     EnableItem(FileMenu,iClose);
  879.     
  880.     DisableItem(FileMenu,iSave);
  881.     DisableItem(FileMenu,iSaveAs);
  882.     DisableItem(FileMenu,iSaveACopy);
  883.     DisableItem(FileMenu,iRevert);
  884.     DisableItem(FileMenu,iPageSetup);
  885.     DisableItem(FileMenu,iPrint);
  886.         
  887.     /* Edit Menu */
  888.     DisableItem(EditMenu,iUndo);
  889.     DisableItem(EditMenu,iCut);
  890.     DisableItem(EditMenu,iCopy);
  891.     DisableItem(EditMenu,iPaste);    
  892.     DisableItem(EditMenu,iClear);
  893.     DisableItem(EditMenu,iSelectAll);
  894.     EnableItem(EditMenu,iShowClipboard);
  895.     DisableItem(EditMenu,iFormat);
  896.     
  897.     DisableItem(EditMenu,iAlign);
  898.     DisableItem(EditMenu,iShiftRight);
  899.     DisableItem(EditMenu,iShiftLeft);
  900.     
  901.     EnableItem(FileMenu,0);
  902.     EnableItem(EditMenu,0);
  903.     DisableItem(FindMenu,0);
  904.     DisableItem(MarkMenu,0);
  905.     EnableItem(WindowMenu,0);
  906.     DisableItem(ConvertMenu,0);
  907. }
  908.  
  909. void clipbooardDoContent(WindowPtr wind,EventRecord *event)
  910. {
  911.     Rect contents;
  912.  
  913.     FocusOnWindow(wind);
  914.     GlobalToLocal(&event->where);
  915.     (*((DocumentPeek)wind)->getContentRect)(wind,&contents);
  916.     if(!PtInRect(event->where,&contents))
  917.         ScrollClick(wind,event);
  918. }
  919.  
  920. void clipboardDoIdle(WindowPtr wind)
  921. {
  922.     TE32KHandle tH;
  923.         
  924.     if(tH = (TE32KHandle)gClipboardDoc->docData)
  925.         if((**tH).caretState)
  926.             xorCaret(tH);
  927. }
  928.  
  929. static DocumentPeek OpenClipboardWindow(void)
  930. {
  931.     DocumentPeek doc;
  932.     TE32KHandle tH;
  933.     Rect wRect;
  934.     Str255 clipTitle;
  935.     
  936.     GetIndString(clipTitle,129,5);            /* "Clipboard" */
  937.     if(doc = MakeDoc('TEXT',0)) {
  938.         if(((*doc->makeWindow)((WindowPtr)doc)) && ((*doc->initDoc)((WindowPtr)doc))) {
  939.             /* Read only methods */
  940.             doc->doKeyDown=nullEventMethod;
  941.             doc->doCut=nullWindowMethod;
  942.             doc->doCopy=nullWindowMethod;
  943.             doc->doPaste=nullWindowMethod;
  944.             doc->doClear=nullWindowMethod;
  945.             doc->doUndo=nullWindowMethod;
  946.             doc->writeDocFile=nullIntMethod;
  947.             doc->destructor=clipboardDestructor;
  948.             doc->adjustDocMenus=clipboardAdjustDocMenus;
  949.             doc->doContent=clipbooardDoContent;
  950.             doc->doIdle=clipboardDoIdle;
  951.  
  952.             /* Make the default a non-wrapping window. */
  953.             tH=(TE32KHandle)doc->docData;
  954.             (**tH).crOnly=true;
  955.             (**tH).wrapToLength=false;
  956.             /* Make it a low, wide window on the bottom of the screen. */
  957.             wRect = DragBoundsRect;    
  958.             InsetRect(&wRect,10,10);
  959.             wRect.top=wRect.bottom-130;
  960.             SizeDocWindow((WindowPtr)doc,&wRect,true);
  961.             
  962.             TE32KPaste(tH);
  963.             SetDocWindowTitle((WindowPtr)doc, clipTitle);
  964.             ShowDocWindow((WindowPtr)doc);
  965.             GetIndString(clipTitle,129,4);
  966.             SetItem(EditMenu,iShowClipboard,clipTitle);
  967.             InitCursor();
  968.         } else {
  969.             DeleteDoc(doc);
  970.             doc=0;
  971.         }
  972.     }
  973.     return doc;
  974. }
  975.  
  976. void OpenWorksheetDoc(void)
  977. {
  978.     Str255 VolandWSNames;
  979.     OSErr err;
  980.     short vRefNum;
  981.     long response=0;
  982.     
  983.     err = GetVol(VolandWSNames, &vRefNum);
  984.     GetIndString(VolandWSNames,131,1);
  985.     if(Gestalt(gestaltFSAttr,&response)==noErr)
  986.         err = FSMakeFSSpec(vRefNum,0,VolandWSNames,&HomeSpecs);
  987.     else
  988.         err = glueFSMakeFSSpec(vRefNum,0,VolandWSNames,&HomeSpecs);
  989.     err=CloseWD(vRefNum);
  990.     
  991.     DefaultSpecs=HomeSpecs;
  992.     if(gUseWorksheet) {
  993.         if(!(gPlainTextWSDoc=(DocumentPeek)InitOldDoc('TEXT',&HomeSpecs)))
  994.             MakeWorksheetDoc(&HomeSpecs);
  995.     }
  996. }
  997.  
  998. /*------------------------------- Preferences ----------------------------*/
  999.  
  1000. static void getAppPreferences(void)
  1001. {
  1002.     Str255 worksheetChoice,buf;
  1003.     
  1004.     GetItem(EditMenu,iWorksheet,worksheetChoice);
  1005.     GetIndString(buf,129,1);
  1006.     gUseWorksheet = !IUCompString(worksheetChoice,buf);
  1007. }
  1008.  
  1009. static void setUseWorksheet(void)
  1010. {
  1011.     Str255 buf;
  1012.     
  1013.     if(gUseWorksheet) {
  1014.         GetIndString(buf,129,2);
  1015.         SetItem(EditMenu,iWorksheet,buf);
  1016.         if(gPlainTextWSDoc)
  1017.             CloseADoc((WindowPtr)gPlainTextWSDoc);
  1018.         gUseWorksheet = !gUseWorksheet;
  1019.         gPlainTextWSDoc=0;
  1020.     } else {
  1021.         GetIndString(buf,129,1);
  1022.         SetItem(EditMenu,iWorksheet,buf);
  1023.         gUseWorksheet = !gUseWorksheet;
  1024.         if(!(gPlainTextWSDoc=(DocumentPeek)InitOldDoc('TEXT',&HomeSpecs)))
  1025.             MakeWorksheetDoc(&HomeSpecs);
  1026.     }
  1027.     CalcMenuSize(EditMenu);        /* because there is a bug in the Menu Manager */
  1028.     DeleteMenu(EDIT_ID);        /* now remove menu so we can manipulate it */
  1029.     (**EditMenu).menuProc=0;    /* set to proc id, instead of proc handle */
  1030.     ChangedResource((Handle)EditMenu);    /* now save the resource */
  1031.     WriteResource((Handle)EditMenu);
  1032.     ReleaseResource((Handle)EditMenu);
  1033.     EditMenu=GetMenu(EDIT_ID);            /* and get it again */
  1034.     InsertMenu(EditMenu,FIND_ID);
  1035.     DrawMenuBar();
  1036. }
  1037.  
  1038. /*---------------------------------- main --------------------------------*/
  1039.  
  1040. main()
  1041. {
  1042.     long response=0;
  1043.     
  1044.     UnloadSeg((Ptr)_DataInit);                /* throw out setup code */
  1045.  
  1046.     if(!SetUpWorld())
  1047.         ExitToShell();
  1048.     setUpMenus();
  1049.     
  1050.     getAppPreferences();
  1051.     
  1052.     UnloadSeg((Ptr)SetUpWorld);                /* get rid of my initialization code */
  1053.  
  1054.     if(Gestalt(gestaltAppleEventsAttr,&response)==noErr) 
  1055.         InitAEStuff();
  1056.     else {
  1057.         OpenWorksheetDoc();
  1058.         OpenDocFromFinder();
  1059.     }
  1060.     eventLoop();
  1061.     
  1062. }
  1063.  
  1064. void minimain(void)
  1065. {
  1066.     EventRecord minievent;
  1067.     short code;    
  1068.     
  1069.     while (WaitNextEvent(activMask+updateMask+app4Mask+mDownMask,&minievent,gSleepTime,NIL)) {    
  1070.         switch (minievent.what) {
  1071.             case updateEvt:
  1072.                 UpdateEvt(&minievent);
  1073.                 break;
  1074.             case activateEvt:
  1075.                 ActivateEvt(&minievent);
  1076.                 break;
  1077.             case osEvt:
  1078.                 code=(minievent.message>>24)&0x0FF;
  1079.                 if (code==suspendResumeMessage) {
  1080.                     if (minievent.message&resumeFlag)    /* resume event */
  1081.                         DoResume(&minievent,0);        
  1082.                     else    /* suspend event */
  1083.                         DoSuspend(&minievent,0);        /* suspend event*/
  1084.                 }
  1085.                 break;
  1086.             default:
  1087.                 SysBeep(2);
  1088.         }
  1089.     }
  1090. }
  1091.  
  1092. void OSEvent(EventRecord *event) 
  1093. {
  1094.     Boolean doConvert;
  1095.     unsigned char evType;
  1096.     
  1097.     evType = (unsigned char)(event->message >>24)&0x0FF;
  1098.     
  1099.     switch(evType) {
  1100.         case mouseMovedMessage:
  1101.             AppIdle(FindDoc(FrontLayer()));
  1102.             break;
  1103.         case suspendResumeMessage:
  1104.             doConvert=event->message&2;
  1105.             if (event->message&resumeFlag) {
  1106.                 gInBackground=false;
  1107.                 DoResume(event,doConvert);
  1108.             } else {
  1109.                 gInBackground=true;
  1110.                 DoSuspend(event,doConvert);
  1111.             }
  1112.             break;
  1113.         default:
  1114.             break;
  1115.     }
  1116. }
  1117.  
  1118. void GetClipFromSystem(void)
  1119. {
  1120.     OSErr err;
  1121.     
  1122.     err = TE32KFromScrap();
  1123. /*    gClipType = 'TEXT';    */
  1124. }
  1125.  
  1126. void GiveClipToSystem(void)
  1127. {
  1128.     PScrapStuff scrapInfo;
  1129.     OSErr err;
  1130.     
  1131.     err = TE32KToScrap();
  1132.  
  1133.     scrapInfo = InfoScrap();
  1134.     gLastScrapCount = scrapInfo->scrapCount;
  1135. }
  1136.  
  1137. Boolean ClipHasChanged(void)
  1138. {
  1139.     PScrapStuff scrapInfo = InfoScrap();
  1140.     return (scrapInfo->scrapCount != gLastScrapCount);
  1141. }
  1142.  
  1143. void CheckForDASwitch(WindowPtr theFrontWindow)
  1144. {
  1145.     Boolean DAWindowOnTop;
  1146.     
  1147.     if(theFrontWindow) {
  1148.         DAWindowOnTop = ((WindowPeek)theFrontWindow)->windowKind<0;
  1149.         if(DAWindowOnTop != gDAonTop) {
  1150.             if(gDAonTop = DAWindowOnTop) 
  1151.                 GiveClipToSystem();
  1152.             else if(ClipHasChanged())
  1153.                 GetClipFromSystem();
  1154.         }
  1155.     }
  1156. }
  1157.  
  1158. /*------------------------------ DoSuspend--------------------------------*/
  1159.  
  1160. void DoSuspend(EventRecord *theEvent,Boolean convertClip)
  1161. {
  1162.     WindowPtr targetWindow;
  1163.     
  1164.     if(convertClip)
  1165.         GiveClipToSystem();
  1166.     targetWindow=FrontLayer();
  1167.     if(FindDoc(targetWindow)) {    /* Is it a Documents window? */
  1168.         theEvent->modifiers &= (!activeFlag);
  1169.         DoActivate(targetWindow,theEvent);
  1170.     }
  1171. }    
  1172.         
  1173. /*------------------------------ DoResume --------------------------------*/
  1174.  
  1175. void DoResume(EventRecord *theEvent, Boolean convertClip) 
  1176. {
  1177.     WindowPtr targetWindow;
  1178.     
  1179.     targetWindow=FrontLayer();         /* What window is it in?  */
  1180.     
  1181.     if(convertClip)
  1182.         GetClipFromSystem();
  1183.     
  1184.     if(FindDoc(targetWindow)) {    /* Is it a Documents window? */
  1185.         theEvent->modifiers |= activeFlag;
  1186.         DoActivate(targetWindow,theEvent);
  1187.     }
  1188. }
  1189.  
  1190. int CloseADoc(WindowPtr wind)
  1191. {
  1192.     if(((DocumentPeek)wind)->fDocWindow) {    /* Document is active */
  1193.         if(DoClose(wind)) {
  1194.             (*((DocumentPeek)wind)->destructor)(wind);
  1195.             
  1196.             AdjustMenus(FrontLayer());
  1197.             DrawMenuBar();
  1198.             return 1;
  1199.         }
  1200.         return 0;
  1201.     }
  1202.     return 1;
  1203. }
  1204.  
  1205. WindowPtr OpenNamedFile(Str255 fileName)
  1206. {
  1207.     FSSpec spec;
  1208.     char *p;
  1209.     HFileInfo pB;
  1210.     OSErr err;
  1211.     long response=0;
  1212.     
  1213.     p=ConditionFileName((char*)fileName);
  1214.     c2pstr(p);
  1215.     
  1216.     if(Gestalt(gestaltFSAttr,&response)==noErr)
  1217.         err=FSMakeFSSpec(DefaultSpecs.vRefNum,DefaultSpecs.parID,(StringPtr)p,&spec);
  1218.     else
  1219.         err=glueFSMakeFSSpec(DefaultSpecs.vRefNum,DefaultSpecs.parID,(StringPtr)p,&spec);
  1220.  
  1221.     memset(&pB,0,sizeof(HFileInfo));
  1222.     pB.ioVRefNum=spec.vRefNum;
  1223.     pB.ioDirID=spec.parID;
  1224.     pB.ioNamePtr=spec.name;
  1225.     err=PBGetCatInfoSync((CInfoPBPtr)&pB);
  1226.     if(err!=noErr)
  1227.         return 0;
  1228.     if(AcceptableFileType(pB.ioFlFndrInfo.fdType))
  1229.         return InitOldDoc(pB.ioFlFndrInfo.fdType,&spec);
  1230.     return 0;
  1231. }
  1232.  
  1233. /*------------------------------------------------------------------------
  1234.     Open a file, given an FSSpec. First get and check the type. Called 
  1235.     from Open and Print Apple Events.
  1236. -------------------------------------------------------------------------*/
  1237.  
  1238. WindowPtr OpenOldFile(FSSpec *spec) {
  1239.     HFileInfo pB;
  1240.     OSErr err;
  1241.  
  1242.     memset(&pB,0,sizeof(HFileInfo));
  1243.     pB.ioVRefNum=spec->vRefNum;
  1244.     pB.ioDirID=spec->parID;
  1245.     pB.ioNamePtr=spec->name;
  1246.     err=PBGetCatInfoSync((CInfoPBPtr)&pB);
  1247.     if(err!=noErr)
  1248.         return 0;
  1249.  
  1250.     if(AcceptableFileType(pB.ioFlFndrInfo.fdType))
  1251.         return InitOldDoc(pB.ioFlFndrInfo.fdType,spec);
  1252.     return 0;
  1253. }
  1254.  
  1255. void OpenOldDoc(int how)
  1256. {
  1257.     StandardFileReply reply;
  1258.     long response=0;
  1259.     DocumentPeek doc;
  1260.  
  1261.     InitCursor();
  1262.     if(Gestalt(gestaltStandardFileAttr,&response)==noErr)
  1263.         StandardGetFile(NIL,(how)?-1:NumFileTypes,MyFileTypes,&reply);
  1264.     else
  1265.         glueStandardGetFile(NIL,(how)?-1:NumFileTypes,MyFileTypes,&reply);
  1266.     if(reply.sfGood) {
  1267.         if(doc=(DocumentPeek)InitOldDoc((how)?'TEXT':reply.sfType,&reply.sfFile)) {
  1268.             if(how) {
  1269.                 /* Read only if option key held down */
  1270.                 doc->doKeyDown=nullEventMethod;
  1271.                 doc->doCut=nullWindowMethod;
  1272.                 doc->doCopy=nullWindowMethod;
  1273.                 doc->doPaste=nullWindowMethod;
  1274.                 doc->doClear=nullWindowMethod;
  1275.                 doc->doUndo=nullWindowMethod;
  1276.                 doc->writeDocFile=nullIntMethod;
  1277.             }
  1278.         }
  1279.     }
  1280. }
  1281.  
  1282. WindowPtr InitOldDoc(OSType type, FSSpecPtr fileInfo)
  1283. {
  1284.     DocumentPeek doc;
  1285.     int i,n;
  1286.     Rect r;
  1287.     
  1288.     for(i=n=0;n<NumWindows;i++) {
  1289.         doc=Documents+i;
  1290.         if(doc->fDocWindow) {
  1291.             n++;
  1292.             if(doc->fDocType==type && doc->fileSpecs.vRefNum==fileInfo->vRefNum
  1293.                     && doc->fileSpecs.parID==fileInfo->parID
  1294.                     && *doc->fileSpecs.name==*fileInfo->name
  1295.                     && !strncmp(doc->fileSpecs.name+1,fileInfo->name+1,*fileInfo->name))
  1296.                 return (WindowPtr)doc;
  1297.         }
  1298.     }
  1299.     if(doc = (DocumentPeek)MakeDoc(type,fileInfo)) {
  1300.         if(((*doc->makeWindow)((WindowPtr)doc)) && ((*doc->initDoc)((WindowPtr)doc))) {
  1301.             if(OpenDocFile((WindowPtr)doc)) {
  1302.                 if((*doc->readDocFile)((WindowPtr)doc)) {
  1303.                     if(doc->resourcePathRefNum) {
  1304.                         if(doc->windowState) {
  1305.                             r = ((MPSRPtr)*doc->windowState)->userState;
  1306.                             r.top-=20;
  1307.                             SizeDocWindow((WindowPtr)doc,&r,true);
  1308.                         }
  1309.                     }
  1310.                     ShowDocWindow((WindowPtr)doc);
  1311.                     if(doc->marks) 
  1312.                         FillMarkMenu(doc);
  1313.                 } else {
  1314.                     CloseDocFile(doc);
  1315.                     DeleteDoc(doc);
  1316.                     return 0;
  1317.                 }
  1318.             } else {
  1319.                 DeleteDoc(doc);
  1320.                 return 0;
  1321.             }
  1322.         } else {
  1323.             DeleteDoc(doc);
  1324.             doc=0;
  1325.         }
  1326.     }
  1327.     return (WindowPtr)doc;
  1328. }
  1329.  
  1330. Boolean OpenDocFromFinder(void)
  1331. {
  1332.     short message;
  1333.     short count,i;
  1334.     AppFile theApp;
  1335.     FSSpec spec;
  1336.     Boolean fileOpened = false, hasFSSpec;
  1337.     OSErr err;
  1338.     long response=0;
  1339.     
  1340.     CountAppFiles(&message,&count);
  1341.     if(!count)
  1342.         return false;
  1343.         
  1344.     hasFSSpec=(Gestalt(gestaltFSAttr,&response)==noErr);
  1345.     for(i=count;i;i--) {
  1346.         GetAppFiles(i,&theApp);
  1347.         if(hasFSSpec)
  1348.             err=FSMakeFSSpec(theApp.vRefNum,0,theApp.fName,&spec);
  1349.         else
  1350.             err=glueFSMakeFSSpec(theApp.vRefNum,0,theApp.fName,&spec);
  1351.         
  1352.         if(AcceptableFileType(theApp.fType))
  1353.             if(InitOldDoc(theApp.fType,&spec))
  1354.                 fileOpened = true;
  1355.     }
  1356.     return fileOpened;
  1357. }
  1358.  
  1359. Boolean AcceptableFileType(OSType theType)
  1360. {
  1361.     OSType *theTypeList;
  1362.     int i;
  1363.     
  1364.     theTypeList = MyFileTypes;
  1365.     
  1366.     if((NumFileTypes == 0) || (theTypeList == nil))
  1367.         return true;
  1368.     
  1369.     for(i=0; i<NumFileTypes; i++) {
  1370.         if(theType == *theTypeList++)
  1371.             return true;
  1372.     }
  1373.     return false;
  1374. }
  1375.  
  1376.  
  1377. void OpenNewDoc(void)
  1378. {
  1379.     DocumentPeek newDoc;
  1380.     FSSpec spec;
  1381.     
  1382.     spec=DefaultSpecs;
  1383.     GetIndString(spec.name,131,3);
  1384.  
  1385.     if(newDoc = MakeDoc('TEXT',&spec)) {
  1386.         if(((*newDoc->makeWindow)((WindowPtr)newDoc)) && ((*newDoc->initDoc)((WindowPtr)newDoc))) {
  1387.             /* Now make the data entry doc */
  1388.             AdjustScrollBars((WindowPtr)newDoc);
  1389.             SetScrollBarValues((WindowPtr)newDoc);
  1390.             newDoc->fNeedtoSaveAs=true;
  1391. /*========= (*newDoc->newState)((WindowPtr)newDoc);    */
  1392.             ShowDocWindow((WindowPtr)newDoc);
  1393.         } else 
  1394.             DeleteDoc(newDoc);
  1395.     }
  1396. }
  1397.  
  1398. void MakeWorksheetDoc(FSSpecPtr specs)
  1399. {
  1400.     if(!gPlainTextWSDoc) {
  1401.         if(gPlainTextWSDoc = MakeDoc('TEXT',specs)) {
  1402.             if( (*gPlainTextWSDoc->makeWindow)((WindowPtr)gPlainTextWSDoc) &&
  1403.                     (*gPlainTextWSDoc->initDoc)((WindowPtr)gPlainTextWSDoc)) {
  1404.                 ShowDocWindow((WindowPtr)gPlainTextWSDoc);
  1405.                 gPlainTextWSDoc->fNeedtoSaveAs=false;
  1406.                 gPlainTextWSDoc->fNeedtoSave=false;
  1407.             } else {
  1408.                 DeleteDoc(gPlainTextWSDoc);
  1409.                 gPlainTextWSDoc=0;
  1410.             }
  1411.         }
  1412.     }
  1413. }
  1414.  
  1415.  
  1416. void WindowMenuSelect(short docNumber)
  1417. {
  1418.     short i,cnt;
  1419.     
  1420.     for(i=cnt=0;i<MAXWINDS;i++) {
  1421.         if(Documents[i].fDocWindow) {
  1422.             if(++cnt == docNumber) {
  1423.                 if((WindowPtr)(Documents+i) != FrontLayer())
  1424.                     SelectWindow((WindowPtr)(Documents+i));
  1425.                 return;
  1426.             }
  1427.         }
  1428.     }
  1429. }
  1430.  
  1431. /*    For apps having non-text windows, SizeDocWindow should be a member function
  1432.     and share code with doGrow. */
  1433.  
  1434. void SizeDocWindow(WindowPtr wind, Rect *newSize,Boolean makeFront)
  1435. {
  1436.     TE32KHandle tH;
  1437.     Rect r;
  1438.     
  1439.     if(((DocumentPeek)wind)->docData) {
  1440.         FocusOnWindow(wind);
  1441.         r = wind->portRect;
  1442.         r.left = r.right-15;
  1443.         InvalRect(&r);
  1444.         
  1445.         r = wind->portRect;    
  1446.         r.top = r.bottom-15;
  1447.         InvalRect(&r);
  1448.         
  1449.         MoveWindow(wind,newSize->left,newSize->top+20,makeFront);
  1450.         SizeWindow(wind,newSize->right-newSize->left,newSize->bottom-newSize->top-20,false);
  1451.  
  1452.         r = wind->portRect;
  1453.         r.left = r.right-15;
  1454.         EraseRect(&r);
  1455.         InvalRect(&r);
  1456.         
  1457.         r = wind->portRect;
  1458.         r.top = r.bottom-15;
  1459.         EraseRect(&r);
  1460.         InvalRect(&r);
  1461.         
  1462.         SizeScrollBars(wind);
  1463. #if 0
  1464.         if(!makeFront) {
  1465.             if(((DocumentPeek)wind)->vScroll)
  1466.                 HideControl(((DocumentPeek)wind)->vScroll);
  1467.             if(((DocumentPeek)wind)->hScroll)
  1468.                 HideControl(((DocumentPeek)wind)->hScroll);
  1469.         }
  1470. #endif
  1471.         if(SetTERect(wind)) {
  1472.             TE32KCalText(tH=(TE32KHandle)((DocumentPeek)wind)->docData);
  1473.             TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  1474.         }
  1475.         AdjustScrollBars(wind);
  1476.         SetScrollBarValues(wind);
  1477.         DrawGrowIcon(wind);
  1478.         GetContentRect(wind,&r);
  1479.         InvalRect(&r);
  1480.         EraseRect(&r);
  1481.     }
  1482.     return;
  1483. }
  1484.  
  1485. void TileWindows(void)
  1486. {
  1487.     int i,j,nWinds,nRows,nCols;
  1488.     short wWidth,wHeight;
  1489.     Rect base,wRect;
  1490.     DocumentPeek doc;
  1491.     WindowPtr front;
  1492.     
  1493.     front=0;
  1494.     for(nWinds=i=0;i<MAXWINDS;i++) {
  1495.         if((Documents+i)!=gPlainTextWSDoc && Documents[i].docData) {
  1496.             if(!front)
  1497.                 front=(WindowPtr)&Documents[i];
  1498.             nWinds++;
  1499.         }
  1500.     }
  1501.     if(nWinds) {
  1502.         nCols=0;
  1503.         do {
  1504.             nRows = nWinds/++nCols;
  1505.         } while(nRows>nCols+2);
  1506.         
  1507.         wWidth=(DragBoundsRect.right-DragBoundsRect.left-(nCols-1)*4)/nCols;
  1508.         wHeight=(DragBoundsRect.bottom-DragBoundsRect.top-4-(nRows-1)*4)/nRows;
  1509.         base=DragBoundsRect;
  1510.         base.top+=4;
  1511.         base.right=base.left+wWidth;
  1512.         base.bottom=base.top+wHeight;
  1513.         doc=&Documents[0];
  1514.         for(i=0;i<nCols;i++) {
  1515.             for(j=0;j<nRows;j++) {
  1516.                 wRect=base;
  1517.                 OffsetRect(&wRect,(wWidth+4)*i,(wHeight+4)*j);
  1518.                 while(!doc->docData && doc!=gPlainTextWSDoc && doc<&Documents[MAXWINDS-1])
  1519.                     doc++;
  1520.                 SizeDocWindow((WindowPtr)doc,&wRect,!front);
  1521.                 doc++;
  1522.             }
  1523.         }
  1524.         if(front)
  1525.             SelectWindow(front);
  1526.     }
  1527. }
  1528.  
  1529. void StackWindows(void)
  1530. {
  1531.     int i,nWinds;
  1532.     short shift;
  1533.     Rect base,wRect;
  1534.     WindowPtr wind;
  1535.     
  1536.     for(nWinds=0,i=1;i<MAXWINDS;i++) {
  1537.         if(Documents[i].docData) 
  1538.             nWinds++;
  1539.     }
  1540.     if(gPlainTextWSDoc)
  1541.         nWinds--;
  1542.     base=DragBoundsRect;
  1543.     base.top+=2;
  1544.     shift=10*nWinds;
  1545.     base.right-=shift;
  1546.     base.bottom-=shift;
  1547.     
  1548.     for(wind=FrontLayer();wind;
  1549.         wind=(WindowPtr)((WindowPeek)wind)->nextWindow) {
  1550.         if(wind!=(WindowPtr)gPlainTextWSDoc) {
  1551.             shift=10*nWinds;
  1552.             wRect=base;
  1553.             OffsetRect(&wRect,shift,shift);
  1554.             wRect.top=base.top+20*nWinds;
  1555.             SizeDocWindow(wind,&wRect,false);
  1556.             nWinds--;
  1557.         }
  1558.     }
  1559. }
  1560.  
  1561. /*----------------------- File I/O glues -----------------------------*/
  1562.  
  1563. #ifdef Sys6Glues
  1564.  
  1565. #pragma segment glues
  1566.  
  1567. pascal OSErr glueFSMakeFSSpec(short volRefNum,long dirID,
  1568.                         ConstStr255Param fileName,FSSpecPtr spec)
  1569. {
  1570.     OSErr err;
  1571.     short newVolRefNum;
  1572.     long newDirID;
  1573.     HFileInfo pB;
  1574.     Str255 temp;
  1575.     char *p;
  1576.  
  1577.     err=GetWDInfo(volRefNum,&newVolRefNum,&newDirID,0);
  1578.     if(err==noErr) {
  1579.         dirID=(dirID)?dirID:newDirID;
  1580.         volRefNum=newVolRefNum;
  1581.     }
  1582.     
  1583.     if(*fileName) {
  1584.         BlockMove(fileName,temp,*fileName+1);
  1585.         *(temp+*fileName+1)='\0';
  1586.         if(isfullpath(temp+1)) {
  1587.             err=GetVolRefNum(temp,&volRefNum);
  1588.             if(err!=noErr) {
  1589.                 BlockMove(temp,spec->name,*temp+1);
  1590.                 return err;
  1591.             }
  1592.             BlockMove(fileName,temp,*fileName+1);
  1593.             *(temp+*fileName+1)='\0';
  1594.         }
  1595.     } else
  1596.         *temp=0;
  1597.     
  1598.     memset(&pB,0,sizeof(HFileInfo));
  1599.     pB.ioNamePtr=temp;
  1600.     pB.ioDirID=dirID;
  1601.     pB.ioVRefNum=volRefNum;
  1602.  
  1603.     /*  PBGetCatInfo with pB.ioFDirIndex==0 doesn't work if there
  1604.         is no file name. */
  1605.     if(!*temp) 
  1606.         pB.ioFDirIndex=-1;
  1607.  
  1608.     err=PBGetCatInfoSync((CInfoPBPtr)&pB);
  1609.     spec->vRefNum=pB.ioVRefNum;
  1610.     spec->parID=pB.ioFlParID;
  1611.     BlockMove(temp,spec->name,*temp+1);
  1612.     if(err==noErr) {
  1613.         if(*temp) {
  1614.             /*    Whether a file or a directory, the name is incorect */
  1615.             if(pB.ioFlAttrib&16) { /* We have a directory but not a directory name */
  1616.                 pB.ioFDirIndex=-1;
  1617.                 *temp=0;
  1618.                 err=PBGetCatInfoSync((CInfoPBPtr)&pB);
  1619.                 BlockMove(temp,spec->name,*temp+1);
  1620.             } else {
  1621.                 p=strrchr(temp+1,':');
  1622.                 p=(p)? p+1:temp+1;
  1623.                 *spec->name=strlen(p);
  1624.                 BlockMove(p,spec->name+1,*spec->name);
  1625.             }
  1626.         }
  1627.     }
  1628.     return err;
  1629. }
  1630.  
  1631. pascal void glueStandardGetFile(FileFilterProcPtr, 
  1632.         short numTypes, SFTypeList typeList, StandardFileReply *reply)
  1633. {
  1634.     SFReply oldReply;
  1635.     FInfo finderInfo;
  1636.     Point p;
  1637.     OSErr err;
  1638.     
  1639.     p.h = (DragBoundsRect.right-DragBoundsRect.left-344)/2; 
  1640.     p.v = DragBoundsRect.top+60;
  1641.     oldReply.good = FALSE;
  1642.     oldReply.fName[0]= 0;
  1643.     
  1644.     SFGetFile(p, NIL, NIL, numTypes, typeList, NIL, &oldReply);
  1645.     reply->sfGood=oldReply.good;
  1646.     reply->sfReplacing=false;
  1647.     reply->sfType=oldReply.fType;
  1648.     reply->sfScript=-1;
  1649.     reply->sfIsFolder=false;
  1650.     reply->sfIsVolume=false;
  1651.     reply->sfReserved1=0;
  1652.     reply->sfReserved2=0;
  1653.     if(oldReply.good) {
  1654.         err=GetWDInfo(oldReply.vRefNum,&reply->sfFile.vRefNum,&reply->sfFile.parID,0);
  1655.         if(err==noErr) {
  1656.             strncpy(reply->sfFile.name+1,oldReply.fName+1,oldReply.fName[0]);
  1657.             reply->sfFile.name[0]=oldReply.fName[0];
  1658.         }
  1659.         err=GetFInfo(oldReply.fName,oldReply.vRefNum,&finderInfo);
  1660.         reply->sfFlags=finderInfo.fdFlags;
  1661.         err=CloseWD(oldReply.vRefNum);
  1662.     }
  1663. }
  1664.  
  1665. pascal void glueStandardPutFile(ConstStr255Param prompt,
  1666.           ConstStr255Param defaultName, StandardFileReply *reply)
  1667. {
  1668.     SFReply oldReply;
  1669.     Point p;
  1670.     OSErr err;
  1671.         
  1672.     p.h = (DragBoundsRect.right-DragBoundsRect.left-344)/2; 
  1673.     p.v = DragBoundsRect.top+60;
  1674.     SFPutFile(p,prompt,defaultName,(DlgHookProcPtr)nil,&oldReply);
  1675.     reply->sfGood=oldReply.good;
  1676.     if(!oldReply.good) {
  1677.         /* the user canceled the SaveAs */
  1678.         return;
  1679.     }
  1680.     reply->sfReplacing=false;
  1681.     reply->sfScript=-1;
  1682.     reply->sfIsFolder=false;
  1683.     reply->sfIsVolume=false;
  1684.     reply->sfReserved1=false;
  1685.     reply->sfReserved2=false;
  1686.     err=GetWDInfo(oldReply.vRefNum,&reply->sfFile.vRefNum,&reply->sfFile.parID,0);
  1687.     if(err==noErr) {
  1688.         strncpy(reply->sfFile.name+1,oldReply.fName+1,oldReply.fName[0]);
  1689.         reply->sfFile.name[0]=oldReply.fName[0];
  1690.     }
  1691.     err=CloseWD(oldReply.vRefNum);
  1692. }
  1693.  
  1694. #endif
  1695.  
  1696. #pragma segment marks
  1697.  
  1698. MarkRecPtr GetIndMark(Ptr mark, short index)
  1699. {
  1700.     short nMarks,i;
  1701.     
  1702.     nMarks = *((short *) mark);
  1703.     mark += 2;
  1704.     for(i=0;i<index && i<nMarks; i++) 
  1705.          mark+=sizeofMark(mark);
  1706.     return (i==index)? (MarkRecPtr)mark : 0;
  1707. }
  1708.  
  1709. Ptr switchMarks(MarkRecPtr m0,MarkRecPtr m1)
  1710. {
  1711.     Str255 temp;
  1712.     Ptr m;
  1713.     
  1714.     m=(Ptr)m1;
  1715.     m+=m1->label-m0->label;
  1716.     BlockMove(m0,temp,m0->label+9);
  1717.     BlockMove(m1,m0,m1->label+9);
  1718.     BlockMove(temp,m,9+((MarkRecPtr)temp)->label);
  1719.     return m;
  1720. }
  1721.  
  1722. int ConfirmDialog(short strID,Str255 message)
  1723. {
  1724.     DialogPtr confirmDialog;
  1725.     short itemHit,itemType;
  1726.     Handle itemHand;
  1727.     Rect box;
  1728.     Str255 buf,a;
  1729.     
  1730.     GetIndString(buf,128,strID);
  1731.     *(buf+*buf+1)=0;
  1732.     *a=sprintf(a+1,buf+1,message+1);
  1733.  
  1734.     confirmDialog=GetNewDialog(rConfirmDialog,(Ptr)&DlogStor,(WindowPtr)(-1));
  1735.  
  1736.     if(!confirmDialog) 
  1737.         FatalError();
  1738.     GetDItem(confirmDialog,3,&itemType,&itemHand,&box);
  1739.     SetIText(itemHand,a);
  1740.     GetDItem(confirmDialog,4,&itemType,&itemHand,&box);
  1741.     SetDItem(confirmDialog,4,itemType,(Handle)doButton,&box);
  1742.         
  1743.     for(;;) {
  1744.         ModalDialog(DialogStandardFilter,&itemHit);
  1745.         
  1746.         if(itemHit==1) {                /* Okay */
  1747.             CloseDialog(confirmDialog);
  1748.             return 1;
  1749.         } else if(itemHit==2) {
  1750.             CloseDialog(confirmDialog);
  1751.             return 0;
  1752.         }
  1753.     }
  1754. }
  1755.  
  1756. /* nameRequested is a c string */
  1757.  
  1758. int RequestDialog(short strID,char *nameRequested)
  1759. {
  1760.     DialogPtr requestDialog;
  1761.     short itemHit,itemType;
  1762.     Handle itemHand;
  1763.     Rect box;
  1764.     char *p;
  1765.     Str255 message;
  1766.  
  1767.     requestDialog=GetNewDialog(rRequestDialog,(Ptr)&DlogStor,(WindowPtr)(-1));
  1768.  
  1769.     if(!requestDialog) 
  1770.         FatalError();
  1771.         
  1772.     /*    Truncate the selection to one line and make it less than 63 chars. */
  1773.     for(p=nameRequested;*p && *p!='\n';p++) ;
  1774.     *p='\0';
  1775.     c2pstr(nameRequested);
  1776.     if(*nameRequested>63)
  1777.         *nameRequested=63;
  1778.     *(nameRequested+*nameRequested+1)=0;
  1779.     
  1780.     GetDItem(requestDialog,3,&itemType,&itemHand,&box);
  1781.     GetIndString(message,128,strID);    
  1782.     SetIText(itemHand,message);
  1783.     GetDItem(requestDialog,4,&itemType,&itemHand,&box);
  1784.     SetIText(itemHand,nameRequested);
  1785.     SelIText(requestDialog,4,0,32767);
  1786.     GetDItem(requestDialog,5,&itemType,&itemHand,&box);
  1787.     SetDItem(requestDialog,5,itemType,(Handle)doButton,&box);
  1788.     
  1789.     for(;;) {
  1790.         
  1791.         ModalDialog(DialogStandardFilter,&itemHit);
  1792.  
  1793.         if(itemHit==1) {                    /* Okay */
  1794.             GetDItem(requestDialog,4,&itemType,&itemHand,&box);
  1795.             GetIText(itemHand,nameRequested);
  1796.             if(*nameRequested>63)
  1797.                 *nameRequested=63;
  1798.             CloseDialog(requestDialog);
  1799.             return 1;
  1800.         } else if(itemHit==2) {                /* Cancel */
  1801.             CloseDialog(requestDialog);
  1802.             return 0;
  1803.         }
  1804.     }
  1805. }
  1806.  
  1807. void sortMarks(DocumentPeek doc, Boolean how)
  1808. {
  1809.     Ptr mark,firstMark;
  1810.     short i,nMarks;
  1811.     Boolean changed;
  1812.     MarkRecPtr m0,m1;
  1813.     
  1814.     if(doc->marks) {
  1815.         HLock(doc->marks);
  1816.         mark = *doc->marks;
  1817.         nMarks = *((short *)mark);
  1818.         firstMark=mark+2;
  1819.         /* This is a unidirectional bubble sort. */
  1820.         do {
  1821.             mark=firstMark;
  1822.             m1=(MarkRecPtr)mark;
  1823.             for(nMarks--,changed=i=0;i<nMarks;i++) {
  1824.                 m0=m1;
  1825.                 mark+=9+m1->label;
  1826.                 m1=(MarkRecPtr)mark;
  1827.                 if((how)?    m0->selStart>m1->selStart :
  1828.                             IUCompString(&m0->label,&m1->label)>0) {
  1829.                     mark=switchMarks(m0,m1);
  1830.                     m1=(MarkRecPtr)mark;
  1831.                     changed=true;
  1832.                 }
  1833.             }
  1834.         } while(changed);
  1835.         HUnlock(doc->marks);
  1836.         FillMarkMenu(doc);
  1837.     }
  1838. }
  1839.  
  1840. void InsertMark(DocumentPeek doc,int selStart,int selEnd,char *p)
  1841. {
  1842.     Ptr mark,firstMark;
  1843.     short i,nMarks,itemType;
  1844.     OSErr err;
  1845.     MarkRecPtr m0;
  1846.     int whereInMarks,oldSize,newSize;
  1847.     
  1848.     /*    p is the tentative mark name and is a c string when passed,
  1849.         but is turned into a pstring by RequestDialog. */
  1850.         
  1851.     if(RequestDialog(1,p)) {
  1852.         if(doc->marks) {
  1853.             HLock(doc->marks);
  1854.             mark = *doc->marks;
  1855.             nMarks = *((short *)mark);
  1856.             firstMark=mark+2;
  1857.             i=*p;
  1858.             if(!(i%2)) {
  1859.                 (*p)++;
  1860.                 p[*p]='\0';
  1861.             }
  1862.             whereInMarks=Munger(doc->marks,2,p,*p+1,0,0);
  1863.             if(whereInMarks>=0) {        /* This mark already exists */
  1864.                 *p=i;
  1865.                 if(ConfirmDialog(2,p)) {
  1866.                     *p+=(i%2)? 0:1;
  1867.                     m0 = (MarkRecPtr)(mark+whereInMarks-8);
  1868.                     m0->selStart=selStart;
  1869.                     m0->selEnd=selEnd;
  1870.                 }
  1871.                 return;
  1872.             }
  1873.             /* Insert a new mark. Put it at beginning of new Handle so the bubble sort will
  1874.                 position it in one iteration. */
  1875.             HUnlock(doc->marks);
  1876.             oldSize=GetHandleSize(doc->marks);
  1877.             newSize=*p+(((*p)%2)? 9:10);
  1878.             SetHandleSize(doc->marks,oldSize+newSize);
  1879.             err=MemError();
  1880.             if(err==noErr) {
  1881.                 HLock(doc->marks);
  1882.                 BlockMove(*doc->marks+2,*doc->marks+newSize+2,oldSize-2);
  1883.                 *((short *)*doc->marks)=nMarks+1;
  1884.                 m0 = (MarkRecPtr)(*doc->marks + 2);
  1885.                 m0->selStart=selStart;
  1886.                 m0->selEnd=selEnd;
  1887.                 BlockMove(p,&m0->label,*p+1);
  1888.                 HUnlock(doc->marks);
  1889. #if 0
  1890.                 if(doc->resourcePathRefNum)
  1891.                     ChangedResource(doc->marks);
  1892. #endif
  1893.                 GetItemMark(MarkMenu,iAlphabetical,&itemType);
  1894.                 sortMarks(doc,!itemType);    /* Calls FillMarkMenu */
  1895.             } else {
  1896.                 /* A mem error */ 
  1897.             
  1898.             }
  1899.         } else {
  1900.             newSize=*p+(((*p)%2)? 11:12);
  1901.             doc->marks=NewHandle(newSize);
  1902.             if(doc->marks) {
  1903.                 HLock(doc->marks);
  1904.                 *((short *)*doc->marks)=1;
  1905.                 m0 = (MarkRecPtr)(*doc->marks + 2);
  1906.                 m0->selStart=selStart;
  1907.                 m0->selEnd=selEnd;
  1908.                 BlockMove(p,&m0->label,*p+1);
  1909.                 if(!(m0->label%2)) {
  1910.                     m0->label++;
  1911.                     p=&m0->label;
  1912.                     p[m0->label]='\0';
  1913.                 }
  1914.                 HUnlock(doc->marks);
  1915.                 FillMarkMenu(doc);
  1916.             }
  1917.         }
  1918.     }
  1919. }
  1920.  
  1921. ListHandle FillMarkList(DocumentPeek doc,WindowPtr unMarkDialog, int selStart, int selEnd)
  1922. {
  1923.     short i,nMarks;
  1924.     Ptr mark;
  1925.     MarkRecPtr m0;
  1926.     ListHandle theList=0;
  1927.     Rect box,dataBounds;
  1928.     Point cellSize,cell;
  1929.     short itemType;
  1930.     Handle itemHand;
  1931.     
  1932.     nMarks = *((short *)*doc->marks);
  1933.     
  1934.     GetDItem(unMarkDialog,4,&itemType,&itemHand,&box);
  1935.     InsetRect(&box,1,1);
  1936.  
  1937.     cellSize.v=15;
  1938.     cellSize.h=box.right-box.left;
  1939.  
  1940.     box.bottom=box.top+cellSize.v*((box.bottom-box.top)/cellSize.v);
  1941.     box.right-=15;
  1942.  
  1943.     SetRect(&dataBounds,0,0,1,nMarks);
  1944.     theList=LNew(&box,&dataBounds,cellSize,0,unMarkDialog,FALSE,FALSE,FALSE,TRUE);
  1945.     if(!theList) {
  1946.         SysBeep(2);
  1947.         return 0;
  1948.     }
  1949.  
  1950.     HLock(doc->marks);
  1951.  
  1952.     cell.h=0;
  1953.     cell.v=0;
  1954.     mark=*doc->marks+2;
  1955.     for(i=0;i<nMarks;i++) {
  1956.         m0=(MarkRecPtr)mark;
  1957.         LSetCell(mark+9,m0->label,cell,theList);
  1958.         if(m0->selStart==selStart && m0->selEnd==selEnd)
  1959.             LSetSelect(true,cell,theList);
  1960.         cell.v++;
  1961.         mark+= 9+m0->label;
  1962.     }
  1963.     HUnlock(doc->marks);
  1964.     return theList;
  1965. }
  1966.  
  1967. short DeleteMark(DocumentPeek doc,short markIndex)
  1968. {
  1969.     short nMarks,i;
  1970.     Ptr mark;
  1971.     long len,delta,newSize;
  1972.     
  1973.     if(doc->marks) {
  1974.         nMarks=*((short *)*doc->marks);
  1975.         if(markIndex>nMarks)
  1976.             return nMarks;
  1977.         if(--nMarks) {
  1978.             len=GetHandleSize(doc->marks);
  1979.             HLock(doc->marks);
  1980.             *((short *)*doc->marks)=nMarks;
  1981.             mark=*doc->marks + 2;
  1982.             for(i=0;i<markIndex;i++)
  1983.                 mark+=9+((MarkRecPtr)mark)->label;
  1984.             delta = 9 + ((MarkRecPtr)mark)->label;
  1985.             newSize=(long)StripAddress(*doc->marks);
  1986.             newSize+=len;
  1987.             newSize-=(long)StripAddress(mark);
  1988.             newSize-=delta;
  1989.  
  1990.             if(markIndex<nMarks)    /* not last mark to be deleted */
  1991.                 BlockMove(mark+delta,mark,newSize);
  1992.             HUnlock(doc->marks);
  1993.             newSize=len-delta;
  1994.             SetHandleSize(doc->marks,newSize);
  1995.             i=(short)MemError();
  1996.             if(i!=noErr) {
  1997.                 DisposeHandle(doc->marks);
  1998.                 doc->marks=0;
  1999.             }
  2000.         } else {
  2001.             SetHandleSize(doc->marks,2);
  2002.             *((short *)*doc->marks)=nMarks;
  2003.         }
  2004.         FillMarkMenu(doc);
  2005.         return nMarks;
  2006.     }
  2007. }
  2008.  
  2009. /*---------------------------------------------------------------------------
  2010.     This is a universal filter for modal dialogs that use List Manager lists.
  2011.     It does the conventional checking for double clicks and return or enter
  2012.     key hits.
  2013. -----------------------------------------------------------------------------*/
  2014.  
  2015. pascal Boolean listFilter(DialogPtr dialog,EventRecord *theEvent,short *itemHit)
  2016. {
  2017.     ListHandle list;
  2018.     Point mouseLoc,cell;
  2019.     short modifiers;
  2020.     Rect box;
  2021.     short itemType;
  2022.     Handle itemHand;
  2023.     Boolean selected;
  2024.     
  2025.     SetPort(dialog);
  2026.     GetDItem(dialog,1,&itemType,&itemHand,&box);
  2027.  
  2028.     cell.h=cell.v=0;
  2029.     list=(ListHandle)GetWRefCon(dialog);
  2030.     selected=LGetSelect(true,&cell,list);
  2031.     
  2032.     if(theEvent->what==mouseDown) {
  2033.         mouseLoc=theEvent->where;
  2034.         modifiers=theEvent->modifiers;
  2035.         GlobalToLocal(&mouseLoc);
  2036.         if(LClick(mouseLoc,modifiers,list)) {    /* Double Click */
  2037.             *itemHit=1;
  2038.             return true;
  2039.         }
  2040.     } else if(theEvent->what==keyDown) {
  2041.         if(DialogStandardKeyDown(dialog,theEvent,itemHit))
  2042.             return true;
  2043.     }
  2044.     HiliteControl((ControlHandle)itemHand,(selected)? 0:255);
  2045.     return false;
  2046. }
  2047.  
  2048. void UpdateList (ListHandle TheListHandle)
  2049. {
  2050.     Rect ViewRect;
  2051.     RgnHandle ListUpdateRgn;
  2052.  
  2053.     SetPort((**TheListHandle).port);
  2054.     /*    Get the List manager to update the list. */
  2055.     ViewRect = (**TheListHandle).rView;
  2056.     LDoDraw(true, TheListHandle);
  2057.     ListUpdateRgn = NewRgn();
  2058.     RectRgn(ListUpdateRgn,&ViewRect);
  2059.     LUpdate(ListUpdateRgn, TheListHandle);
  2060.     /*    Draw the border */
  2061.     InsetRect(&ViewRect, -1, -1);
  2062.     FrameRect(&ViewRect);
  2063.     /*    Clean up after ourselves */
  2064.       DisposeRgn(ListUpdateRgn);
  2065. }
  2066.  
  2067. void DoUnmark(DocumentPeek doc,int selStart,int selEnd)
  2068. {
  2069.     DialogPtr unmarkDialog;
  2070.     Boolean pau=false;
  2071.     short itemHit,itemType;
  2072.     Handle itemHand;
  2073.     ListHandle list;
  2074.     Rect box;
  2075.     Point cell;
  2076.     Str255 buf;
  2077.     
  2078.     unmarkDialog=GetNewDialog(rUnmarkDialog,(Ptr)&DlogStor,(WindowPtr)(-1));
  2079.  
  2080.     if(!unmarkDialog) 
  2081.         FatalError();
  2082.     
  2083.     if(list=FillMarkList(doc,unmarkDialog,selStart,selEnd)) {
  2084.         SetWRefCon(unmarkDialog,(long)list);
  2085.         LAutoScroll(list);
  2086.         UpdateList(list);
  2087.                 
  2088.         GetIndString(buf,128,5);
  2089.         GetDItem(unmarkDialog,3,&itemType,&itemHand,&box);
  2090.         SetIText(itemHand,buf);
  2091.         
  2092.         GetDItem(unmarkDialog,5,&itemType,&itemHand,&box);
  2093.         SetDItem(unmarkDialog,5,itemType,(Handle)doButton,&box);
  2094.  
  2095.         while(!pau) {
  2096.             ModalDialog(listFilter,&itemHit);
  2097.                 if(itemHit==1) {            /* Okay */
  2098.                 pau=true;
  2099.                 cell.h=cell.v=0;
  2100.                 for(itemType=0;LGetSelect(true,&cell,list);itemType++) {
  2101.                     DeleteMark(doc,cell.v-itemType);
  2102.                     cell.v++;
  2103.                 }
  2104.             } else if(itemHit==2) {        /* Cancel */
  2105.                 pau=true;
  2106.             }
  2107.         }
  2108.     }
  2109.     LDispose(list);
  2110.     CloseDialog(unmarkDialog);
  2111. }
  2112.  
  2113.  
  2114. /*    
  2115.     This works okay. It operates directly on the MENU resource in memory.
  2116.      This is not illegal.
  2117. */
  2118. void FillMarkMenu(DocumentPeek doc)
  2119. {
  2120.     register Ptr mark,dest;
  2121.     register int i,j,nMarks;
  2122.     Boolean order=false,putUp;
  2123.     Size baseLength,markLength;
  2124.     
  2125.     OSErr err;
  2126.     CursHandle cH;
  2127.     
  2128.     if(doc->markMenu) {
  2129.         cH=GetCursor(watchCursor);
  2130.         if(cH)
  2131.             SetCursor(*cH);
  2132.  
  2133.         if(putUp=(StripAddress(MarkMenu)==StripAddress(doc->markMenu)))
  2134.             DeleteMenu(MARK_ID);
  2135.             
  2136.         DisposeHandle((Handle)doc->markMenu);
  2137.         doc->markMenu=(MenuHandle)GetResource('MENU',MARK_ID);
  2138.         err=HandToHand((Handle *)&doc->markMenu);
  2139.         if(err!=noErr)
  2140.             return;
  2141.             
  2142.         if(doc->marks) {
  2143.             nMarks=*(short *)*doc->marks;
  2144.             
  2145.             /* Later on, only do the following if nMarks>50 */
  2146.             
  2147.             baseLength=GetHandleSize((Handle)doc->markMenu);
  2148.             markLength=GetHandleSize(doc->marks)-nMarks*4-2;
  2149.             
  2150.             SetHandleSize((Handle)doc->markMenu,baseLength+markLength);
  2151.             err=MemError();
  2152.             if(err!=noErr)
  2153.                 return;
  2154.                     
  2155.             HLock(doc->marks);
  2156.     
  2157.             /* 1. Check for order */
  2158.             mark=*doc->marks+2;
  2159.             for(j=i=0;i<nMarks;i++,mark+=sizeofMark(mark)) {
  2160.                 if(j>((MarkRecPtr)mark)->selStart) {
  2161.                     CheckItem(doc->markMenu,iAlphabetical,true);
  2162.                     break;
  2163.                 }
  2164.                 j=((MarkRecPtr)mark)->selStart;
  2165.             }
  2166.             mark=*doc->marks+10;
  2167.             
  2168.             /* 2. Move the mark labels into the MENU resource structure */
  2169.             HLock((Handle)doc->markMenu);
  2170.             memset((*((Handle)doc->markMenu))+baseLength,0,markLength);
  2171.             
  2172.             mark=*doc->marks+10;
  2173.             dest=(*((Handle)doc->markMenu))+baseLength-1;
  2174.                         
  2175.             while(nMarks) {
  2176.                 for(j=*mark+1,i=0;i<j;i++) 
  2177.                     *dest++ = *mark++;
  2178.                 mark+=8;
  2179.                 dest+=4;
  2180.                 nMarks--;
  2181.             }
  2182.                 
  2183.             HUnlock(doc->marks);
  2184.             HUnlock((Handle)doc->markMenu);
  2185.             
  2186.             CalcMenuSize(doc->markMenu);
  2187.             
  2188.             if(putUp) {
  2189.                 MarkMenu=doc->markMenu;
  2190.                 InsertMenu(MarkMenu,WINDOW_ID);
  2191.             }
  2192.         }
  2193.     }
  2194.     InitCursor();
  2195. }
  2196.  
  2197. /*----------------------------------------------------------------------
  2198.  
  2199.     Marks whose selBegin is greater than a value are moved by delta, 
  2200.     whether delta is positive or negative.
  2201.  
  2202.     Marks whose selEnd is less than a value are not changed.
  2203.  
  2204.     If delta is negative then marks completely enclosed in a range are 
  2205.     deleted.
  2206.  
  2207.     Marks that are intersected by a range are extended or decreased.
  2208.  
  2209.     The range and delta can usually be determined from the undo 
  2210.     parameters. In continuous typing, however, this is not possible as 
  2211.     an event that triggers a need to update the mark (e.g. a mouse-down 
  2212.     in the menu bar) may not trigger the formation of a new undo buffer.
  2213.     
  2214. -----------------------------------------------------------------------*/
  2215.  
  2216. void UpdateMarks(DocumentPeek doc,long selStart,long selEnd,long delta, long docLength)
  2217. {
  2218.     Ptr mark;
  2219.     short nMarks,i,mSize;
  2220.  
  2221. #if 0
  2222. /*=============== Debug Code ===========*/
  2223.     long offset;
  2224.     TE32KHandle tH;
  2225.     MarkRecPtr theMark;
  2226.     char *p,*q;
  2227. /*=============== Debug Code ===========*/
  2228. #endif
  2229.     if(doc->marks && delta) {
  2230.         HLock(doc->marks);
  2231.         nMarks = *((short *)*doc->marks);
  2232.         mark=*doc->marks+2;
  2233.         
  2234.         /*    
  2235.             If a mark is deleted, mSize is set to zero so that we won't increment 
  2236.             past the newly current mark. 
  2237.         */
  2238.             
  2239.         for(i=0;i<nMarks;i++,mark+=mSize) {
  2240.             mSize = sizeofMark(mark);
  2241.             
  2242.             if(selStart <= selEnd) {
  2243.                 if(selEnd < ((MarkRecPtr)mark)->selStart) {    
  2244.                     /*     
  2245.                         Most common case: 
  2246.                             No overlap with mark and mark is after the edited region. 
  2247.                     */
  2248.                     
  2249.                     ((MarkRecPtr)mark)->selStart += delta;
  2250.                     ((MarkRecPtr)mark)->selEnd += delta;
  2251.                     
  2252.                 } else if(selStart<((MarkRecPtr)mark)->selStart 
  2253.                             && selEnd>((MarkRecPtr)mark)->selEnd) {
  2254.                     /* 
  2255.                         Extreme case: 
  2256.                             Change overlaps both ends of mark. Either delete or move mark.
  2257.                     */
  2258.                     
  2259.                     if(delta<0) {                    /* Negative delta means text has been deleted. */
  2260.                         nMarks=DeleteMark(doc,i);    /* N.B. DeleteMark unlocks doc->marks handle. */
  2261.                         if(nMarks) {
  2262.                             HLock(doc->marks);
  2263.                             mark=(Ptr)GetIndMark(*doc->marks,i--);
  2264.                             if(!mark) {
  2265.                                 HUnlock(doc->marks);
  2266.                                 return;
  2267.                             }
  2268.                         }  
  2269.                         mSize=0;
  2270.                     } else {                        /* Text added. Move mark. */
  2271.                         ((MarkRecPtr)mark)->selStart += delta;
  2272.                         ((MarkRecPtr)mark)->selEnd += delta;
  2273.                     }
  2274.                 } else if(selStart <= ((MarkRecPtr)mark)->selEnd 
  2275.                         || selEnd <= ((MarkRecPtr)mark)->selEnd) {
  2276.                     /*
  2277.                         Mark partially overlapped by edited region.
  2278.                     */
  2279.                     
  2280.                     ((MarkRecPtr)mark)->selEnd += delta;
  2281.                 }
  2282.             } else {
  2283.                 if(selStart < ((MarkRecPtr)mark)->selStart) {    
  2284.                     /* Most common case: No overlap. */
  2285.                     ((MarkRecPtr)mark)->selStart += delta;
  2286.                     ((MarkRecPtr)mark)->selEnd += delta;
  2287.                 } else if(selEnd<((MarkRecPtr)mark)->selStart && selStart>((MarkRecPtr)mark)->selEnd) {
  2288.                     /* Extreme case, change overlaps both end. */
  2289.                     if(delta<0) {
  2290.                         ((MarkRecPtr)mark)->selStart = selEnd;
  2291.                         ((MarkRecPtr)mark)->selEnd = selEnd;
  2292.                     } else {
  2293.                         ((MarkRecPtr)mark)->selStart += delta;
  2294.                         ((MarkRecPtr)mark)->selEnd += delta;
  2295.                     }
  2296.                 } else if(selEnd <= ((MarkRecPtr)mark)->selStart) {        /* deleting back through beginning of mark */
  2297.                     if(delta<0) {
  2298.                         ((MarkRecPtr)mark)->selStart = selEnd;
  2299.                         ((MarkRecPtr)mark)->selEnd = selEnd;
  2300.                     } else {
  2301.                         ((MarkRecPtr)mark)->selStart += (selStart-selEnd);
  2302.                         ((MarkRecPtr)mark)->selEnd += delta;
  2303.                     }
  2304.                     
  2305.                 } else if(selEnd <= ((MarkRecPtr)mark)->selEnd) {        /* deleting back and encountering mark    */
  2306.                     if(delta<0)
  2307.                         ((MarkRecPtr)mark)->selEnd = selEnd;
  2308.                     else
  2309.                         ((MarkRecPtr)mark)->selEnd += (selStart-selEnd);
  2310.                 }
  2311.             }
  2312.             /*
  2313.                 If a mark is beyond the current document. Delete it. 
  2314.             */
  2315.             if(mSize && docLength>=0 && (((MarkRecPtr)mark)->selEnd>docLength 
  2316.                         || ((MarkRecPtr)mark)->selStart>docLength)) { 
  2317.                 if(nMarks=DeleteMark(doc,i)) {
  2318.                     HLock(doc->marks);
  2319.                     mark=(Ptr)GetIndMark(*doc->marks,i--);
  2320.                     if(!mark) {
  2321.                         HUnlock(doc->marks);
  2322.                         return;
  2323.                     }
  2324.                 }
  2325.                 mSize=0;
  2326.             }  
  2327.         }
  2328.         if(doc->marks)        /* It could have been disposed of. */
  2329.             HUnlock(doc->marks);
  2330.     }
  2331.     doc->fNeedtoUpdateMarks = false;
  2332.     
  2333. #if 0
  2334. /*=============== Debug Code ===========*/
  2335.  
  2336.     tH = (TE32KHandle)doc->docData;
  2337.     if(tH && doc->marks) {
  2338.         theMark = (MarkRecPtr)(*doc->marks+2);
  2339.         offset = theMark->selStart;
  2340.         p=*(**tH).hText+offset;
  2341.         q=&theMark->label;
  2342.         if(*p != q[1])
  2343.             SysBeep(7);
  2344.         offset=*q;
  2345.         if(!*(q+offset))
  2346.             offset--;
  2347.         if(*(p+offset-1) != *(q+offset))
  2348.             SysBeep(7);
  2349.     }
  2350. #endif
  2351. }
  2352.  
  2353. #pragma segment appleevents
  2354.  
  2355. /*--------------InitAEStuff installs AppleEvent handlers ----------------*/
  2356.  
  2357. void InitAEStuff(void)
  2358. {
  2359.     AEinstalls HandlersToInstall[] =  
  2360.         {     { kCoreEventClass, kAEOpenApplication, AEOpenHandler    },
  2361.             { kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler    },
  2362.             { kCoreEventClass, kAEQuitApplication, AEQuitHandler    },
  2363.             { kCoreEventClass, kAEPrintDocuments, AEPrintHandler    }, 
  2364.             /* The above are the four required AppleEvents. */
  2365.         };
  2366.     OSErr aevtErr = noErr;
  2367.     register qq;
  2368.  
  2369.     /*    
  2370.         The following series of calls installs all our AppleEvent Handlers.
  2371.         These handlers are added to the application event handler list that 
  2372.         the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  2373.         and we call AEProcessEvent, the AppleEvent manager will check our
  2374.         list of handlers and dispatch to it if there is one.
  2375.     */
  2376.     for (qq = 0; qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls))); qq++) {
  2377.         aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
  2378.                                             HandlersToInstall[qq].theProc, 0, false);
  2379.         if (aevtErr) {
  2380.             ExitToShell();            /* just fail, baby */
  2381.         }
  2382.     }
  2383. }
  2384.  
  2385. /* This is the standard Open Application event.  */
  2386. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  2387. {
  2388.  
  2389. #pragma unused (messagein,reply,refIn)
  2390.     
  2391.     OpenWorksheetDoc();    
  2392.     return noErr;
  2393. }
  2394.  
  2395. /* end AEOpenHandler */
  2396.  
  2397. /* Open Doc, opens our documents.  Remember, this can happen at application start AND */
  2398. /* anytime else.  If your app is up and running and the user goes to the desktop, hilites one */
  2399. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  2400. /* handler will get called. Which means you don't do any initialization of globals here, or */
  2401. /* anything else except open then doc.  */
  2402. /* SO-- Do NOT assume that you are at app start time in this */
  2403. /* routine, or bad things will surely happen to you. */
  2404.  
  2405. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  2406. {
  2407.     OSErr err;
  2408.     
  2409. #pragma unused (refIn,reply)
  2410.     if(!gPlainTextWSDoc) 
  2411.         OpenWorksheetDoc();
  2412.     err = processOpenPrint(messagein, false);
  2413.     return err;
  2414. }
  2415.  
  2416. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  2417. {                                                           /* no printing handler in yet, so we'll ignore this */
  2418.     OSErr err;
  2419.     
  2420. #pragma unused (refIn,reply)
  2421.    
  2422.     err = processOpenPrint(messagein, true);
  2423.     return err;
  2424. }
  2425.  
  2426. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  2427. {
  2428. #pragma unused (messagein,refIn,reply)
  2429.     QuitTime();
  2430.     return noErr;
  2431. }
  2432.  
  2433. /*-------------------------------------------------------------------------------------
  2434.  
  2435.     MissedAnyParameters
  2436.  
  2437.     Used to check for any unread required parameters. Returns true if we missed at
  2438.     least one.
  2439.  
  2440. --------------------------------------------------------------------------------------*/
  2441.  
  2442. Boolean MissedAnyParameters(AppleEvent *message)
  2443. {
  2444.     OSErr err;
  2445.     DescType ignoredActualType;
  2446.     AEKeyword missedKeyword;
  2447.     Size ignoredActualSize;
  2448.     EventRecord event;
  2449.     
  2450.     err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeKeyword, &ignoredActualType, (Ptr)&missedKeyword,
  2451.                             sizeof(missedKeyword), &ignoredActualSize);
  2452.     
  2453.     /* no error means that we found some more.*/
  2454.     
  2455.     if (!err) {
  2456.         event.message = *(long *)&ignoredActualType;
  2457.         event.where = *(Point *)&missedKeyword;
  2458.         doMessage(7);
  2459.         err = errAEEventNotHandled;
  2460.     }
  2461.     
  2462.     /* errAEDescNotFound means that there are no more parameters. If we get */
  2463.     /* an error code other than that, flag it. */
  2464.     
  2465.     else if (err != errAEDescNotFound) {
  2466.         doMessage(8);
  2467.         
  2468.     }
  2469.     return(err != errAEDescNotFound);
  2470. }
  2471.  
  2472. /*-------------------------------------------------------------------------------------
  2473.  
  2474.      processOpenPrint handles ODOC and PDOC events.  Both events open a document, 
  2475.      one prints it 
  2476. --------------------------------------------------------------------------------------*/
  2477.  
  2478. OSErr processOpenPrint(AppleEvent *messagein, Boolean printIt)
  2479. {
  2480.     OSErr err;
  2481.     OSErr err2;
  2482.     AEDesc theDesc;
  2483.     FSSpec theFSS;
  2484.     register qq;
  2485.     long numFilesToOpen;
  2486.     AEKeyword ignoredKeyWord;
  2487.     DescType ignoredType;
  2488.     Size ignoredSize;
  2489.     WindowPtr wind;
  2490.     
  2491.     err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &theDesc);
  2492.     if (err) 
  2493.         doMessage(9);
  2494.  
  2495.     if (!MissedAnyParameters(messagein)) {
  2496.         
  2497.         /* Got all the parameters we need. Now, go through the direct object, */
  2498.         /* see what type it is, and parse it up. */
  2499.         
  2500.         if (err = AECountItems(&theDesc, &numFilesToOpen)) {
  2501.             doMessage(10);
  2502.         } else {
  2503.             for (qq = 1; ((qq <= numFilesToOpen) && (!err)); ++qq) {
  2504.                 if (err = AEGetNthPtr(&theDesc, qq, typeFSS, &ignoredKeyWord, &ignoredType, (Ptr)&theFSS, sizeof(theFSS),
  2505.                         &ignoredSize)) {
  2506.                     doMessage(11);
  2507.                     
  2508.                 } else {
  2509.                     wind=OpenOldFile(&theFSS);
  2510.                     if(wind) {
  2511.                         DefaultSpecs=theFSS;
  2512.                         /*======= TN 80 technique for setting SF Default Vol =====*/
  2513.                         *(short *)SFSaveDisk = -1 * theFSS.vRefNum;
  2514.                         *(long *)CurDirStore = theFSS.parID; /*==== Global Variable fill =====*/
  2515.                     }
  2516.                 }
  2517.                 if (printIt && wind) {
  2518.                     (*((DocumentPeek)wind)->doPrint)(wind);
  2519.                     CloseADoc(wind);
  2520.                 }
  2521.             }                                                /* for qq = ... */
  2522.         }                                                    /* AECountItems OK */
  2523.     }                                                        /* Got all necessary parameters */
  2524.     
  2525.     if (err2 = AEDisposeDesc(&theDesc)) 
  2526.         doMessage(12);
  2527.  
  2528.     return(err ? err : err2);
  2529. }
  2530.